﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using DailyDiet.Models;
using DailyDiet.util.eventArgs;
using SQLite;

namespace DailyDiet.Services.Impl
{
    public class DietRecorderStorageService : IDietRecorderStorageService {

        /******** 公开变量 ********/
        public const string dbName = "dietRecorder.db";

        public static readonly string dbPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder
                .LocalApplicationData), dbName);

        public SQLiteAsyncConnection Connection =>
            _connection ?? (_connection = new SQLiteAsyncConnection(dbPath));

        /******** 私有变量 ********/
        private SQLiteAsyncConnection _connection;
        private IPreferenceStorage _preference;

        /******** 继承方法 ********/

        /// <summary>
        /// 初始化数据库
        /// </summary>
        /// <returns></returns>
        public async Task InitializeAsync() {
            await Connection.CreateTableAsync<DietRecorder>();
            _preference.Set(DietRecorderStorageConstants.VersionKey,DietRecorderStorageConstants.VERSION);
        }

        /// <summary>
        /// 判断数据库似乎初始化
        /// </summary>
        /// <returns></returns>
        public bool IsInitialized() =>
            _preference.Get(DietRecorderStorageConstants.VersionKey,DietRecorderStorageConstants.DEFAULTVERSION)
                .Equals(DietRecorderStorageConstants.VERSION);

        /// <summary>
        /// 根据id获取一条记录
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<DietRecorder> GetDietRecorderAsync(int id) =>
            await Connection.Table<DietRecorder>()
                .FirstOrDefaultAsync(p => p.Id == id);

        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <param name="dietRecorder"></param>
        /// <returns></returns>
        public async Task Insert(DietRecorder dietRecorder) =>
            await Connection.InsertOrReplaceAsync(dietRecorder);

        /// <summary>
        /// 插入一个list的记录
        /// </summary>
        /// <param name="dietRecorders"></param>
        /// <returns></returns>
        public async Task InsertAll(List<DietRecorder> dietRecorders)
        {
            if (dietRecorders == null || dietRecorders.Count < 1) {
                return;
            }
            await Connection.InsertAllAsync(dietRecorders);
            DateTime dateTime = Convert.ToDateTime(dietRecorders[0].Date);
            string mealTime = dietRecorders[0].MealTimes;
            DietRecorderStorageEvent?.Invoke(this, new DietRecorderStorageEventArgs(dateTime,mealTime));
        }


        /// <summary>
        /// 根据where条件读取一个list的记录
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="skip">跳过多少条</param>
        /// <param name="take">取多少</param>
        /// <returns></returns>
        public async Task<List<DietRecorder>> GetDietRecordersAsync(
            Expression<Func<DietRecorder, bool>> @where, int skip, int take) =>
            await Connection.Table<DietRecorder>().Where(where).Skip(skip).Take(take)
                .ToListAsync();

        /// <summary>
        /// 获取所有用户记录
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<List<DietRecorder>> GetAllDietRecorderAsync(
            Expression<Func<DietRecorder, bool>> @where) =>
            await Connection.Table<DietRecorder>().Where(where).ToListAsync();

        /// <summary>
        /// 断开数据库连接
        /// </summary>
        /// <returns></returns>
        public async Task CloseConnection()
        {
            await _connection.CloseAsync();
            _connection = null;
        }

        public event EventHandler<DietRecorderStorageEventArgs> DietRecorderStorageEvent;


        /*********构造函数**********/
        public DietRecorderStorageService(IPreferenceStorage preference) {
            _preference = preference;
        }
    }
}
